package com.ydzt.fanka.server.endday;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.dom4j.Element;

import com.ydzt.fanka.server.domain.BufferRecord;
import com.ydzt.fanka.server.domain.CommunicationNode;
import com.ydzt.fanka.server.domain.ParamDefine;
import com.ydzt.fanka.server.init.InitData;
import com.ydzt.fanka.server.persistence.BufferStore;
import com.ydzt.fanka.server.utils.ByteConvert;
import com.ydzt.fanka.server.utils.DBHelper;
import com.ydzt.fanka.server.utils.FileUtil;
import com.ydzt.fanka.server.utils.IOUtil;
import com.ydzt.fanka.server.utils.NetUtil;
import com.ydzt.fanka.server.utils.PackageHelper;


public class EndDayServer extends Thread{
	
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
	
	HashMap<String , ParamDefine> paramDefine = InitData.initParamDefine();	
	Connection conn = null;
	byte[] stmtdayByte = null;
	byte[] msgTypeByte = null;
	byte[] msgMgrType = null;
	String msgType = null;
	List<Element> drList = null;
	List<CommunicationNode> broadcastList = null;
	static Logger logger = Logger.getLogger(EndDayServer.class.getName());
	
	@SuppressWarnings("unused")
	private boolean createPackageToDroom(List<CommunicationNode> broadcastList,byte[] pkg){
		try{
			if(broadcastList != null){
				for(Iterator<CommunicationNode> it = broadcastList.iterator(); it.hasNext();){
					BufferRecord bufferTmp = new BufferRecord();
					byte[] pkgTmp = pkg;
					CommunicationNode elm = (CommunicationNode)it.next();
					String recevier = elm.getNodeIP();
					int port = elm.getNodePort();
					byte[] recevierIP = ByteConvert.ipv4Address2BinaryArray(recevier);
					if(port > 32767){
						port = port - 65536;
					}
					byte[] recevierPort = ByteConvert.shortToBytes((short)port);
					System.arraycopy(recevierIP, 0, pkgTmp, 6, 4);
					System.arraycopy(recevierPort, 0, pkgTmp, 10, 2);
					bufferTmp.setBufferContent(pkgTmp);
					bufferTmp.setBufferId(UUID.randomUUID().toString());
					if(0 != BufferStore.writePackageIntoBroadcast(bufferTmp)){
						logger.error("将" + bufferTmp.getBufferId() + "写进broadcast文件夹失败");
						return false;
					}
				}
			}
			return true;
		}
		catch(Exception e){
			logger.error("生成广播报文失败!" + e.getMessage());
			return false;
		}
	}
	
	public void run(){
		while(true){
			byte[] pkg = null;
			stmtdayByte = new byte[4];
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			File f = new File(InitData.endflag);
			if(InitData.nodeType.equals("00")){
				if(f != null){
					//int count = f.listFiles().length;
					File[] fList = f.listFiles();
					int test = fList.length;
					if(test != 0){
						int count = fList.length;
						//List<String> suppliers = new ArrayList<String>();
						//suppliers = DBHelper.getCompareInfoByteStmtDay();
						if(count > 0){//endflag有数据则开始日终
							logger.info("检查到endflag文件夹中有 " + count + "条日终报文");
							//开始日终操作
							logger.info("开始日终操作");
							File currentFile = f.listFiles()[0];
							try {
								pkg = IOUtil.toByteArrayTraditional(currentFile.getAbsolutePath());
							} catch (IOException e) {
							}
							logger.info("读取日终报文成功");
							if(pkg.length == 27){
								System.arraycopy(pkg, 23, stmtdayByte, 0, 4);
								String stmt_day = ByteConvert.bcd2Str(stmtdayByte);
								logger.info("解析该日终报文的结算日期为:" + stmt_day);
								//将结算控制表中的END_STATE更改为NOW(表示正在进行日终)
								DBHelper.setStmtCtlStatusByType("END_STATE", "NOW");
								//DBHelper.setStmtCtlStatusByType("UPDATE_ACCOUNT_STATE", "NOW");
								logger.info("将结算控制表中的END_STATE更改为NOW");
								//检查数据是否处理完成
								logger.info("开始检查数据是否处理完成");
								File fTmpdata = new File(InitData.tmpdata);
								DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "NOW");
								boolean isCompleta = true;
								while(isCompleta){
									long countBuffer = FileUtil.getlist(fTmpdata);
									logger.info("在tmpdata文件夹中发现  " + countBuffer + " 条数据未处理");
									if(countBuffer == 0){//表示tmpdata文件夹中无文件 文件已经被处理完
										DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "END");
										logger.info("tmpdata文件夹中没有发现未处理的数据");
										isCompleta = false;
										//tmpdata处理完成 可以生成当日交易统计
										logger.info("tmpdata文件夹中数据全部处理完成,将进行统计信息生成");
										//设置统计信息生成为NOW
										DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "NOW");
										if(DBHelper.createStatistics()){
											DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "END");
											logger.info("统计信息生成完毕，将对统计信息进行组包并发送给每一个食堂计算机");
											logger.info("开始对统计信息进行组包......");
											logger.info("获取食堂计算机列表");
											broadcastList = DBHelper.getCommunicationNodeByType("DR");
											logger.info("取得以下通信节点");
											for(int i = 0 ;i < broadcastList.size();i ++){
												CommunicationNode commNode = broadcastList.get(i);
												logger.info(commNode.getNodeID() + "/" + commNode.getNodeName() + "/" + commNode.getNodeIP() + "/" + commNode.getNodePort());
											}
											byte[] pkg3001 = PackageHelper.createPackageAboutStatisticsCentre("01","");
											try {
												if(0 == NetUtil.synSendMsg(pkg3001)){
													logger.info("3001报文已发送");
												}
											} catch (Exception e) {
												
											}
											//this.createPackageToDroom(broadcastList, pkg3001);
											//logger.info("3001报文已放入broadcast文件夹等待广播");
											DBHelper.setStmtCtlStatusByType("END_STATE", "END");
											//结算日期更改为下一天
											if(DBHelper.setStmtDay(stmt_day)){
												logger.info("结算日期已经更新为:" + stmt_day);
												currentFile.delete();//日终完成后 删除唯一的2001报文
												//生成下一结算日的结算控制表记录
												if(DBHelper.createStmtCtlRecordByStmtDay(stmt_day)){
													logger.info("生成下一结算日的结算控制表记录成功");
												}
												else{
													logger.error("生成下一结算日的结算控制表记录失败");
												}
											}
											else{
												logger.error("设置结算日期不成功");
											}
										}
										else{
											logger.error("生成统计信息不成功");
										}
									}
									else{
										logger.info("在tmpdata文件夹内发现有  " + countBuffer + " 个文件未处理！");
										logger.info("正在处理....");
										try {
											Thread.sleep(5000);
										} catch (InterruptedException e) {
											e.printStackTrace();
										}
									}
								} 
							}
							else{
								logger.info("日终报文长度错误 不为27长");
							}
							
						}
						else{
							/*
							logger.info("存在尚未完成日终的食堂计算机");
							logger.info("当前已经完成上传对账信息的食堂计算机为:");
							for(int i = 0; i < suppliers.size(); i ++){
								logger.info("食堂计算机节点:" + suppliers.get(i).toString());
							}
							*/
						}
					}
				}
			}
			else{
				if(f != null){
					File[] fList = f.listFiles();
					int test = fList.length;
					if(test != 0){
						try {
							int count = f.listFiles().length;
							logger.info("检查到endflag文件夹中有 " + count + "条日终报文");
							logger.info("食堂收到日终报文");
							File currentFile = f.listFiles()[0];
							pkg = IOUtil.toByteArrayTraditional(currentFile.getAbsolutePath());
							logger.info("读取日终报文成功");
							System.arraycopy(pkg, 23, stmtdayByte, 0, 4);
							String stmt_day = ByteConvert.bcd2Str(stmtdayByte);
							logger.info("解析该日终报文的结算日期为:" + stmt_day);
							//将结算控制表中的END_STATE更改为NOW(表示正在进行日终)
							DBHelper.setStmtCtlStatusByType("END_STATE", "NOW");
							logger.info("将结算控制表中的END_STATE更改为NOW");
							//检查数据是否处理完成
							logger.info("开始检查数据是否处理完成");
							File fTmpdata = new File(InitData.tmpdata);
							DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "NOW");
							boolean isCompleta = true;
							while(isCompleta){
								long countBuffer = FileUtil.getlist(fTmpdata);
								logger.info("在tmpdata文件夹中发现  " + countBuffer + " 条数据未处理");
								if(countBuffer == 0){//表示tmpdata文件夹中无文件 文件已经被处理完
									logger.info("tmpdata文件夹中没有发现未处理的数据");
									DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "END");
									isCompleta = false;
									//tmpdata处理完成 可以生成当日交易统计
									logger.info("tmpdata文件夹中数据全部处理完成,将进行统计信息生成");
									//设置统计信息生成为NOW
									DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "NOW");
									if(DBHelper.createStatistics()){
										DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "END");
										
										logger.info("统计信息生成完毕，将对统计信息进行组包并发送至中心");
										logger.info("开始对统计信息进行组包......");
										byte[] pkg3001 = PackageHelper.createPackageAboutStatistics();
										if(0 == NetUtil.synSendMsg(pkg3001)){
											logger.info("3001报文发送成功");
											logger.info("正在本地处理报表数据");
											if(DBHelper.createReportDataCNTREP()){
												DBHelper.setStmtCtlStatusByType("END_STATE", "END");
												//结算日期更改为下一天
												if(DBHelper.setStmtDay(stmt_day)){
													logger.info("结算日期已设置为:" + stmt_day);
													currentFile.delete();//日终完成后 删除唯一的2001报文
													//生成下一结算日的结算控制表记录
													if(DBHelper.createStmtCtlRecordByStmtDay(stmt_day)){
														logger.info("生成下一结算日的结算控制表记录成功");
														
													}
													else{
														logger.error("生成下一结算日的结算控制表记录失败");
													}
												}
												else{
													logger.error("设置结算日期不成功");
												}
											}
											else{
												logger.error("处理报表数据失败");
											}
										}
										else{
											logger.error("发送对账信息不成功");
										}
									}
									else{
										logger.error("生成统计信息不成功");
									}
								}
								else{
									logger.info("在tmpdata文件夹内发现有  " + countBuffer + " 个文件未处理！");
									logger.info("正在处理....");
									Thread.sleep(5000);
								}
							}
						} catch (IOException e) {
						} catch (InterruptedException e) {
						}
						//日终完成(表中stmtday已经修改   endflag文件已经删除)
						//将包头消息类型改写为2002 处理类型改为0x03 发送给中心 
						msgMgrType = new byte[1];
						msgMgrType[0] = 0x03;
						msgTypeByte = new byte[2];
						msgTypeByte = ByteConvert.str2BcdNormal("2002");//
						System.arraycopy(msgTypeByte, 0, pkg, 0, 2);
						System.arraycopy(msgMgrType, 0, pkg, 12, 1);
						try {
							NetUtil.synSendMsg(pkg);
						} catch (Exception e) {
							logger.error("向中心发射通知日终成功报文出错");
							logger.error(e.getMessage());
						}
					}
					else{
						
					}
				}
				
			}
		}
	}
}
